package com.blog.cmrpersonalblog.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.blog.cmrpersonalblog.dto.user.request.UserBanRequest;
import com.blog.cmrpersonalblog.entity.UserBan;
import com.blog.cmrpersonalblog.mapper.UserBanMapper;
import com.blog.cmrpersonalblog.service.UserActivityService;
import com.blog.cmrpersonalblog.service.UserBanService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.Comparator;

/**
 * 用户禁言服务实现类
 */
@Slf4j
@Service
public class UserBanServiceImpl implements UserBanService {

   @Resource
    private UserBanMapper userBanMapper;

   @Resource
    private UserActivityService userActivityService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean banUser(UserBanRequest banRequest, Long operatorId) {
        try {
            // 验证请求
            String validationError = validateBanRequest(banRequest);
            if (validationError != null) {
                throw new RuntimeException(validationError);
            }

            // 检查是否已经被禁言
            UserBan existingBan = userBanMapper.selectActiveBan(banRequest.getUserId(), banRequest.getBanType());
            if (existingBan != null) {
                throw new RuntimeException("用户已被禁言，无法重复禁言");
            }

            // 创建禁言记录
            UserBan userBan = new UserBan();
            userBan.setUserId(banRequest.getUserId());
            userBan.setBanType(banRequest.getBanType());
            userBan.setBanReason(banRequest.getBanReason());
            userBan.setBanStartTime(LocalDateTime.now());
            userBan.setBanEndTime(banRequest.calculateBanEndTime());
            userBan.setIsPermanent(banRequest.getIsPermanent() != null && banRequest.getIsPermanent() ? 1 : 0);
            userBan.setStatus(1); // 生效中
            userBan.setOperatorId(operatorId);
            userBan.setRelatedCommentId(banRequest.getRelatedCommentId());

            int result = userBanMapper.insert(userBan);
            if (result > 0) {
                // 记录禁言活动
                userActivityService.recordActivity(operatorId, "USER_BANNED", 
                    "禁言用户: " + banRequest.getBanTypeEnum().getDescription(),
                    banRequest.getUserId(), "user", "SUCCESS", 
                    Map.of("banType", banRequest.getBanType(), "duration", banRequest.getBanDurationText()));

                // 发送禁言通知
                if (banRequest.getSendNotification() != null && banRequest.getSendNotification()) {
                    sendBanNotification(userBan);
                }

                log.info("用户禁言成功: userId={}, banType={}, operatorId={}", 
                    banRequest.getUserId(), banRequest.getBanType(), operatorId);
                return true;
            }

            return false;
        } catch (Exception e) {
            log.error("用户禁言失败", e);
            throw new RuntimeException("用户禁言失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unbanUser(Long userId, String banType, Long operatorId) {
        try {
            int result = userBanMapper.unbanUser(userId, banType, operatorId);
            if (result > 0) {
                // 记录解禁活动
                userActivityService.recordActivity(operatorId, "USER_UNBANNED", 
                    "解除用户禁言: " + banType,
                    userId, "user", "SUCCESS", 
                    Map.of("banType", banType));

                // 发送解禁通知
                sendUnbanNotification(userId, banType);

                log.info("用户解禁成功: userId={}, banType={}, operatorId={}", userId, banType, operatorId);
                return true;
            }

            return false;
        } catch (Exception e) {
            log.error("用户解禁失败", e);
            throw new RuntimeException("用户解禁失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchUnbanUsers(List<Long> userIds, String banType, Long operatorId) {
        try {
            int result = userBanMapper.batchUnbanUsers(userIds, banType, operatorId);
            if (result > 0) {
                // 记录批量解禁活动
                userActivityService.recordActivity(operatorId, "BATCH_USER_UNBANNED", 
                    "批量解除用户禁言: " + banType,
                    null, "user", "SUCCESS", 
                    Map.of("banType", banType, "count", result));

                log.info("批量解禁成功: count={}, banType={}, operatorId={}", result, banType, operatorId);
            }

            return result;
        } catch (Exception e) {
            log.error("批量解禁失败", e);
            throw new RuntimeException("批量解禁失败: " + e.getMessage());
        }
    }

    @Override
    public boolean isUserBanned(Long userId, String banType) {
        UserBan activeBan = userBanMapper.selectActiveBan(userId, banType);
        if (activeBan == null) {
            return false;
        }

        // 检查是否过期
        if (activeBan.isExpired()) {
            // 自动解除过期禁言
            try {
                userBanMapper.unbanUser(userId, banType, null);
            } catch (Exception e) {
                log.warn("自动解除过期禁言失败: userId={}, banType={}", userId, banType, e);
            }
            return false;
        }

        return true;
    }

    @Override
    public List<UserBan> getActiveBans(Long userId) {
        return userBanMapper.selectActiveBansByUserId(userId);
    }

    @Override
    public List<UserBan> getUserBanHistory(Long userId) {
        return userBanMapper.selectUserBanHistory(userId);
    }

    @Override
    public IPage<UserBan> getBanRecords(Long current, Long size, Long userId, String banType, Integer status) {
        Page<UserBan> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return userBanMapper.selectBanRecordsPage(page, userId, banType, status);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean extendBanTime(Long banId, Integer additionalMinutes, Long operatorId) {
        try {
            UserBan userBan = userBanMapper.selectById(banId);
            if (userBan == null) {
                throw new RuntimeException("禁言记录不存在");
            }

            LocalDateTime newEndTime;
            if (userBan.isPermanentBan()) {
                throw new RuntimeException("永久禁言无法延长时间");
            } else if (userBan.getBanEndTime() != null) {
                newEndTime = userBan.getBanEndTime().plusMinutes(additionalMinutes);
            } else {
                newEndTime = LocalDateTime.now().plusMinutes(additionalMinutes);
            }

            int result = userBanMapper.extendBanTime(banId, newEndTime, operatorId);
            if (result > 0) {
                // 记录延长禁言活动
                userActivityService.recordActivity(operatorId, "USER_BAN_EXTENDED", 
                    "延长用户禁言时间",
                    userBan.getUserId(), "user", "SUCCESS", 
                    Map.of("banId", banId, "additionalMinutes", additionalMinutes));

                log.info("延长禁言时间成功: banId={}, additionalMinutes={}, operatorId={}", 
                    banId, additionalMinutes, operatorId);
                return true;
            }

            return false;
        } catch (Exception e) {
            log.error("延长禁言时间失败", e);
            throw new RuntimeException("延长禁言时间失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int autoUnbanExpiredBans() {
        try {
            int result = userBanMapper.autoUnbanExpiredBans();
            if (result > 0) {
                log.info("自动解除过期禁言: count={}", result);
            }
            return result;
        } catch (Exception e) {
            log.error("自动解除过期禁言失败", e);
            return 0;
        }
    }

    @Override
    public List<UserBan> getExpiringBans(Integer beforeMinutes) {
        if (beforeMinutes == null || beforeMinutes <= 0) {
            beforeMinutes = 60; // 默认1小时内到期
        }
        return userBanMapper.selectExpiringBans(beforeMinutes);
    }

    @Override
    public Map<String, Object> getBanStatistics() {
        return userBanMapper.selectBanStatistics();
    }

    @Override
    public Map<String, Long> getBanTypeDistribution() {
        List<Map<String, Object>> distribution = userBanMapper.selectBanTypeDistribution();
        Map<String, Long> result = new HashMap<>();
        
        for (Map<String, Object> item : distribution) {
            String typeName = (String) item.get("ban_type");
            Long count = ((Number) item.get("count")).longValue();
            result.put(typeName, count);
        }
        
        return result;
    }

    @Override
    public List<UserBan> getRecentBans(Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 10;
        }
        return userBanMapper.selectRecentBans(limit);
    }

    @Override
    public int getUserBanCount(Long userId) {
        return userBanMapper.countUserBanHistory(userId);
    }

    @Override
    public List<UserBan> getBanOperationsByOperator(Long operatorId, Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 20;
        }
        return userBanMapper.selectBanOperationsByOperator(operatorId, limit);
    }

    @Override
    public String validateBanRequest(UserBanRequest banRequest) {
        if (banRequest.getUserId() == null) {
            return "用户ID不能为空";
        }

        if (!banRequest.isValidBanType()) {
            return "无效的禁言类型";
        }

        if (banRequest.getBanReason() == null || banRequest.getBanReason().trim().isEmpty()) {
            return "禁言原因不能为空";
        }

        if (banRequest.getIsPermanent() != null && banRequest.getIsPermanent()) {
            // 永久禁言不需要验证时长
            return null;
        }

        if (banRequest.getBanDuration() == null && banRequest.getBanEndTime() == null) {
            return "必须指定禁言时长或结束时间";
        }

        if (banRequest.getBanDuration() != null && banRequest.getBanDuration() <= 0) {
            return "禁言时长必须大于0";
        }

        return null; // 验证通过
    }

    @Override
    public Map<String, Object> getUserBanStatus(Long userId) {
        Map<String, Object> status = new HashMap<>();
        List<UserBan> activeBans = getActiveBans(userId);
        
        status.put("isBanned", !activeBans.isEmpty());
        status.put("activeBans", activeBans);
        status.put("banCount", getUserBanCount(userId));
        
        if (!activeBans.isEmpty()) {
            // 找出最严重的禁言类型
            UserBan mostSevereBan = activeBans.stream()
                    .max(Comparator.comparing(ban -> getBanTypeSeverity(ban.getBanType())))
                    .orElse(activeBans.get(0));
            
            status.put("primaryBan", mostSevereBan);
            status.put("primaryBanType", mostSevereBan.getBanType());
            status.put("primaryBanDescription", mostSevereBan.getBanTypeDescription());
        }
        
        return status;
    }

    @Override
    public boolean sendBanNotification(UserBan userBan) {
        try {
            // 这里可以集成消息通知服务
            // 例如：发送邮件、站内信、短信等
            log.info("发送禁言通知: userId={}, banType={}", userBan.getUserId(), userBan.getBanType());
            return true;
        } catch (Exception e) {
            log.error("发送禁言通知失败", e);
            return false;
        }
    }

    @Override
    public boolean sendUnbanNotification(Long userId, String banType) {
        try {
            // 这里可以集成消息通知服务
            log.info("发送解禁通知: userId={}, banType={}", userId, banType);
            return true;
        } catch (Exception e) {
            log.error("发送解禁通知失败", e);
            return false;
        }
    }

    /**
     * 获取禁言类型严重程度
     */
    private int getBanTypeSeverity(String banType) {
        switch (banType) {
            case "COMMENT":
                return 1;
            case "LOGIN":
                return 2;
            case "ALL":
                return 3;
            default:
                return 0;
        }
    }
}
